package com.hjh.netty.elect.demo5.parser.impl;

import cn.hutool.core.util.ArrayUtil;
import com.hjh.netty.elect.config.BeanCopierUtils;
import com.hjh.netty.elect.config.SpringUtils;
import com.hjh.netty.elect.demo3.CharacterConvert;
import com.hjh.netty.elect.demo5.bean.*;
import com.hjh.netty.elect.demo5.enums.UpLoadDataParserEnum;
import com.hjh.netty.elect.demo5.parser.PayLoadParser;
import com.hjh.netty.elect.demo5.parser.UpLoadData;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class PayLoadParserImpl implements PayLoadParser {


    @Override
    public Pmc350DevBean parserPayLoad(Pmc350DevPackage pmc350DevPackage) {
        if (pmc350DevPackage == null) {
            return null;
        }
        Pmc350DevBean pmc350DevBean = new Pmc350DevBean();

        Pmc350DevHeader pmc350DevHeader = new Pmc350DevHeader();
        BeanCopierUtils.copyProperties(pmc350DevPackage, pmc350DevHeader);

        pmc350DevBean.setHeader(pmc350DevHeader);


        if (pmc350DevPackage == null || ArrayUtil.isEmpty(pmc350DevPackage.getPayLoad())) {
            log.info("parser|payLoad is null");
            return pmc350DevBean;
        }
        byte[] payLoad = pmc350DevPackage.getPayLoad();

        ByteBuf buffer = ByteBufAllocator.DEFAULT.heapBuffer(payLoad.length);
        buffer.writeBytes(payLoad);

        //解析报文体的公用部分
        Pmc350DevCommon pmc350DevPayLoadCommon = parserCommon(buffer);
        pmc350DevBean.setCommon(pmc350DevPayLoadCommon);

        //解析报文体的详细部分
        Pmc350DevUpLoadData pmc350DevPayLoadDetail = parserUpLoadData(buffer, pmc350DevBean);
        pmc350DevBean.setUpLoadData(pmc350DevPayLoadDetail);

        log.info("parserPayLoad|pmc350DevBean:{}", pmc350DevBean);

        return pmc350DevBean;
    }

    /**
     * 解析报文体的详细部分
     *
     * @param buffer        upLoadData数据
     * @param pmc350DevBean
     * @return
     */
    private Pmc350DevUpLoadData parserUpLoadData(ByteBuf buffer, Pmc350DevBean pmc350DevBean) {
        Pmc350DevCommon common = pmc350DevBean.getCommon();

        //根据上送类型，上送子类型，版本号获取解析器
        UpLoadDataParserEnum upLoadDataParserEnum = UpLoadDataParserEnum.obtainInstance(common.getUpDataMainType(), common.getUpDataSubType(), common.getUpDataTypeVer());
        if (upLoadDataParserEnum != null) {
            UpLoadData upLoadData = (UpLoadData) SpringUtils.getBean(upLoadDataParserEnum.getParserHandleClz());
            return upLoadData.parserUpLoadData(buffer, pmc350DevBean);
        }

        return null;
    }

    /**
     * 解析报文体的公用部分
     *
     * @param buffer
     * @return
     */
    private Pmc350DevCommon parserCommon(ByteBuf buffer) {
        //  上送类型/子类型 1 字节
        byte uploadType = buffer.readByte();
        //        bit 7~5：表示上送类型 upDataMainType，其中：
        //        001：定时数据上送
        //        002：事件数据上送
        //        003：记录数据上送
        int upDataMainType = AutoSendTool.getLeftNum(uploadType, 3);

        //bit 4~0： 表示上送子类型 upDataSubType，具体查看相关章节
        int upDataSubType = AutoSendTool.getRightNum(uploadType, 5);

        //  分组号及子类型版本号 1 字节
        byte groupNumber = buffer.readByte();
        //bit 7~4 ：分组号 upGrpNum
        int upGrpNum = AutoSendTool.getHeight4(groupNumber);
        //bit 3~0 ：版本号 upDataTypeVer
        int upDataTypeVer = AutoSendTool.getLow4(groupNumber);


        //  数据包标识 1 字节
        int payLoadPackageType = CharacterConvert.byteToInt(buffer.readByte());


        //  子设备标识符 2 字节 预留，为 0
        int subDevId = CharacterConvert.shortToInt(buffer.readShort());

        //  上送时标（年月） 2 字节
        int year = CharacterConvert.shortToInt(buffer.readByte());
        int month = CharacterConvert.shortToInt(buffer.readByte());

        //  上送时标（日时） 2 字节

        int day = CharacterConvert.shortToInt(buffer.readByte());
        int hour = CharacterConvert.shortToInt(buffer.readByte());

        //  上送时标（分秒） 2 字节
        int minute = CharacterConvert.shortToInt(buffer.readByte());
        int second = CharacterConvert.shortToInt(buffer.readByte());

        return Pmc350DevCommon.builder()
                .upDataMainType(upDataMainType)
                .upDataSubType(upDataSubType)
                .upGrpNum(upGrpNum)
                .upDataTypeVer(upDataTypeVer)
                .payLoadPackageType(payLoadPackageType)
                .subDevId(subDevId)
                .year(year)
                .month(month)
                .day(day)
                .hour(hour)
                .minute(minute)
                .second(second)
                .build();
    }
}
